package io.github.rascaler.dcenter.ws;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.TypeReference;
import io.github.rascaler.dcenter.pojo.Candlestick;
import io.github.rascaler.dcenter.pojo.FixedArrayList;
import io.github.rascaler.dcenter.ws.handler.SocketMessageDispatcher;
import io.github.rascaler.dcenter.ws.message.SocketMessage;
import io.netty.handler.codec.http.HttpHeaders;
import io.netty.handler.timeout.IdleStateEvent;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.MultiValueMap;
import org.yeauty.annotation.*;
import org.yeauty.pojo.Session;

import java.io.IOException;
import java.util.Map;

@Slf4j
@ServerEndpoint(path = "${ws.path}",
        port = "${ws.port}",
        readerIdleTimeSeconds = "${ws.readerIdleTimeSeconds}",
        useCompressionHandler = "${ws.useCompressionHandler}",
        eventExecutorGroupThreads="${ws.eventExecutorGroupThreads}",
        maxFramePayloadLength="${ws.maxFramePayloadLength}"
)
public class WebSocketServer {

    @Autowired
    private SocketSessionManager socketSessionManager;

    @Autowired
    private SocketMessageDispatcher dispatcher;

    @BeforeHandshake
    public void handshake(Session session, HttpHeaders headers, @RequestParam String req, @RequestParam MultiValueMap reqMap, @PathVariable String arg, @PathVariable Map pathMap){
        session.setSubprotocols("stomp");
//        if (!"ok".equals(req)){
//            System.out.println("Authentication failed!");
//            session.close();
//        }
    }
    
    @OnOpen
    public void onOpen(Session session, HttpHeaders headers, @RequestParam String req, @RequestParam MultiValueMap reqMap, @PathVariable String arg, @PathVariable Map pathMap){
        socketSessionManager.add(session);
        log.info("地址=>{}已进入频道，本机当前总共有{}连接",
                session.channel().remoteAddress().toString(),
                socketSessionManager.size());
    }

    @OnClose
    public void onClose(Session session) throws IOException {
        socketSessionManager.remove(session);
        log.info("地址=>{}已离开频道,本机当前总共有{}连接",
                session.channel().remoteAddress().toString(),
               socketSessionManager.size());
    }

    @OnError
    public void onError(Session session, Throwable throwable) {
        log.error(String.format("连接通信异常=>%s,关闭连接...", session.channel().remoteAddress().toString()), throwable);
        session.close();
//        socketSessionManager.remove(session);
//        log.info("地址=>{}已离开频道,本机当前总共有{}连接",
//                session.channel().remoteAddress().toString(),
//                socketSessionManager.size());
    }

    @OnMessage
    public void onMessage(Session session, String message) {
        // 心跳通知
        if (message.equals("ping")) {
            log.debug("[心跳监测] {}：连接活跃", session.channel().remoteAddress());
            session.sendText("pong");
            return;
        }
        JSONObject object = JSON.parseObject(message);
        String path = object.getString("path");
        SocketMessage socketMessage = object.toJavaObject(dispatcher.getPayloadTypeReference(path));
        dispatcher.dispatch(session, socketMessage);
    }

    @OnBinary
    public void onBinary(Session session, byte[] bytes) {
        System.out.println("OnBinary");
    }

    @OnEvent
    public void onEvent(Session session, Object evt) {
        if (evt instanceof IdleStateEvent) {
            IdleStateEvent idleStateEvent = (IdleStateEvent) evt;
            switch (idleStateEvent.state()) {
                case READER_IDLE:
                    log.warn("【{}】连接一段时间没有读到数据，关闭空闲连接...", session.channel().remoteAddress());
                    session.close();
                    break;
                case WRITER_IDLE:
                    System.out.println("write idle");
                    break;
                case ALL_IDLE:
                    System.out.println("all idle");
                    break;
                default:
                    break;
            }
        }
    }

}